/**
 * Copyright (c) 2023 murenchao
 * taomu is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.lang

import com.google.common.collect.HashBasedTable
import com.google.common.collect.Table
import cool.taomu.utils.FileUtils
import java.io.File
import java.util.Set
import org.apache.oro.text.perl.Perl5Util
import org.apache.oro.text.regex.PatternMatcherInput
import org.slf4j.LoggerFactory

class TaomuClassLoader extends ClassLoader implements AutoCloseable{
	static val LOG = LoggerFactory.getLogger(TaomuClassLoader);
	Table<String, String, byte[]> providers = HashBasedTable.create();

	new(String path) {
		LOG.info("class loader path:" + path);
		var Set<String> jars = FileUtils.scanningFile(new File(path));
		jars = jars.filter[it.endsWith(".jar")].toSet;
		jars.forEach [
			var jarClass = FileUtils.readJarClass(new File(it));
			jarClass.forEach [ k, v |
				var p5 = new Perl5Util();
				if (!providers.containsRow(k)) {
					providers.put(k, it, v);
				} else if (!p5.match("/module\\-info/", k)) {
					var String itVer;
					var String kVer;
					var itJar = it.substring(it.lastIndexOf("/") + 1);
					var p5ver = new Perl5Util();
					var input = new PatternMatcherInput(itJar);
					if (p5ver.match("/([0-9]+[0-9\\.]+)/", input)) {
						itVer = p5ver.match.toString;
					}
					var kJarPath = providers.row(k).keySet.get(0);
					var kJar = kJarPath.substring(kJarPath.lastIndexOf("/") + 1)
					p5ver = new Perl5Util();
					input = new PatternMatcherInput(kJar);
					if (p5ver.match("/([0-9]+[0-9\\.]+)/", input)) {
						kVer = p5ver.match.toString;
					}
					if (itVer > kVer) {
						providers.remove(k, kJarPath)
						providers.put(k, it, v);
					}
					LOG.debug("类加载时出现重复类==>冲突的jar:" + itJar + "==>已存在jar：" + kJar + "==>冲突的类:" + k);
				}
			]
		]
	}

	override findClass(String name) {
		var result = this.providers.row(name).values;
		if (result.length > 0) {
			var result2 = result.get(0);
			return defineClass(name, result2, 0, result2.length);
		}
		return null;
	}
	
	override close() throws Exception {
		if(this.providers !== null){
			this.providers.clear;
		}
	}
	
}
